#include "Ogre.h"
#include "Player.h"
#include "DestroyGameObjectMessage.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"
#include "GameplayState.h"
#include "Game.h"
#include "Boss.h"
#include "CreatePortalMessage.h"
#include "TileSystem.h"
#include "CreateBulletMessage.h"
#include "Augment.h"
#include "Projectile.h"
#include "../SGD Wrappers/SGD_AudioManager.h"

Ogre::Ogre()
{
	StartAnimation("ogreidle");
	RegisterForEvent("THROW_ROCK");

	SetLevel(GameplayState::GetInstance()->GetMapIndex());
}

void Ogre::Update(float elapsedTime)
{
	dt = elapsedTime;

	if (chargingTimer > 0.0f)
		chargingTimer -= dt;
	if (walkingTimer > 0.0f)
		walkingTimer -= dt;

	Enemy::Update(elapsedTime);

	// failed checks in Enemy::Update
	if (!updating) return;

	// distance from player
	float distToPlayer = GameplayState::GetInstance()->GetPlayer()->GetPosition().x - GetPosition().x;

	aiming.x = distToPlayer < 0 ? -1.0f : 1.0f;

	chargeCooldown -= elapsedTime;
	throwCooldown -= elapsedTime;
}

void Ogre::Render()
{
	/*if (SGD::InputManager::GetInstance()->IsKeyDown(SGD::Key::F4))
		m_iHealth = 0;*/

	Boss::Render();
	AnimationSystem::GetInstance()->Render({ GetPosition().x - Game::GetInstance()->GetCameraPos().x, GetPosition().y - Game::GetInstance()->GetCameraPos().y }, animInfo);
}

/*virtual*/ bool Ogre::DoAttack()
{
	return ((GameplayState::GetInstance()->GetPlayer()->GetPosition() - m_ptPosition).ComputeLength() < 600.0f);
}

/*virtual*/ void Ogre::Attack()
{
	GameplayState *gameplay = GameplayState::GetInstance();
	SGD::Point playerPos = gameplay->GetPlayer()->GetPosition();
	float distToPlayer = (playerPos - m_ptPosition).ComputeLength();

	//if close enough stop advancing and smash
	if (distToPlayer < 45.0f)
	{
		if (animInfo.GetCurrAnimation() != "ogresmash")
			StartAnimation("ogresmash");

		m_vtVelocity.x = 0.0f;
		return;
	}
	// not close enough to smash
	else if (animInfo.GetCurrAnimation() == "ogresmash")
	{
		StartAnimation("ogrewalking");
		walkingTimer = 2.0f;
	}
	// not close enough and not smashing. player is above and not jumping (on a platform)
	else if (throwCooldown <= 0.0f && abs(playerPos.y - m_ptPosition.y) > 50.0f && !gameplay->GetPlayer()->GetIsJumping())
	{
		//Player is overhead... throw rocks.
		throwCooldown = 8.0f;
		StartAnimation("ogrerockthrow");
	}
	// charge the player
	else if (distToPlayer > 100.0f || rand()% 100 < 20)
	{
		if (chargeCooldown <= 0.0f)
		{
			if (!chargeTargetSet)
			{
				chargeTarget = playerPos;
				chargeTargetSet = true;
			}

			chargeCooldown = 10.0f;
			StartAnimation("ogrecharging");
			chargingTimer = 2.0f;
		}
	}

	if (chargingTimer < 0)
	{
		StartAnimation("ogrewalking");
		walkingTimer = 2.0f;
		chargingTimer = 0;
	}

	if (walkingTimer < 0 && chargeCooldown < 0)
	{
		if (!chargeTargetSet)
		{
			chargeTarget = playerPos;
			chargeTargetSet = true;
		}

		chargeCooldown = 10.0f;
		StartAnimation("ogrecharging");
		chargingTimer = 2.0f;
	}
	else if (walkingTimer < 0)
	{
		StartAnimation("ogrerockthrow");
		walkingTimer = 4.0f;
	}

	if (abs(playerPos.x - m_ptPosition.x) > 50.0f)
	{
		if (playerPos.x < m_ptPosition.x)
			MoveLeft();
		else
			MoveRight();

		if (animInfo.GetCurrAnimation() == "ogrecharging" && (m_ptPosition.x > chargeTarget.x - 10 && m_ptPosition.x < chargeTarget.x + 10))
			StartAnimation("ogrewalking");
	}
}

/*virtual*/ void Ogre::EnterIdle()
{
	if (state == State::IDLE) return;
	Enemy::EnterIdle();

	StartAnimation("ogreidle");
}

/*virtual*/ void Ogre::EnterPatrol()
{
	if (state == State::PATROL) return;
	Enemy::EnterPatrol();

	StartAnimation("ogrewalking");
}

/*virtual*/ void Ogre::EnterCloseIn()
{
	if (state == State::CLOSEIN) return;
	Enemy::EnterCloseIn();

	StartAnimation("ogrewalking");
}

/*virtual*/ void Ogre::EnterDead()
{
	if (state == State::DEAD) return;
	Enemy::EnterDead();

	CreatePortalMessage* ptr = new CreatePortalMessage(0, GetPosition().x, GetPosition().y);
	ptr->QueueMessage();
	SetPlayerNextLevel();
	Boss::SaveHighScore();
}

/*virtual*/ void Ogre::MoveLeft(float speed)
{
	if (animInfo.GetCurrAnimation() == "ogrecharging")
	{
		TileSystem *TS = TileSystem::GetInstance();
		GameplayState *gameplay = GameplayState::GetInstance();
		TS->TurnOffTile(gameplay->GetMapIndex(), { m_ptPosition.x - m_szSize.width / 5, m_ptPosition.y - 5 });
		TS->TurnOffTile(gameplay->GetMapIndex(), { m_ptPosition.x - m_szSize.width / 2, m_ptPosition.y - 5 });
		TS->TurnOffTile(gameplay->GetMapIndex(), { m_ptPosition.x - m_szSize.width / 5, m_ptPosition.y - 37 });
		TS->TurnOffTile(gameplay->GetMapIndex(), { m_ptPosition.x - m_szSize.width / 2, m_ptPosition.y - 37 });
		TS->TurnOffTile(gameplay->GetMapIndex(), { m_ptPosition.x - m_szSize.width / 5, m_ptPosition.y - 69 });
		TS->TurnOffTile(gameplay->GetMapIndex(), { m_ptPosition.x - m_szSize.width / 2, m_ptPosition.y - 69 });
		Enemy::MoveLeft(250.0f);
	}
	else
		Enemy::MoveLeft(speed);
}

/*virtual*/ void Ogre::MoveRight(float speed)
{
	if (animInfo.GetCurrAnimation() == "ogrecharging")
	{
		TileSystem *TS = TileSystem::GetInstance();
		GameplayState *gameplay = GameplayState::GetInstance();
		TS->TurnOffTile(gameplay->GetMapIndex(), { m_ptPosition.x + m_szSize.width / 5, m_ptPosition.y - 5 });
		TS->TurnOffTile(gameplay->GetMapIndex(), { m_ptPosition.x + m_szSize.width / 2, m_ptPosition.y - 5 });
		TS->TurnOffTile(gameplay->GetMapIndex(), { m_ptPosition.x + m_szSize.width / 5, m_ptPosition.y - 37 });
		TS->TurnOffTile(gameplay->GetMapIndex(), { m_ptPosition.x + m_szSize.width / 2, m_ptPosition.y - 37 });
		Enemy::MoveRight(250.0f);
	}
	else
		Enemy::MoveRight(speed);
}

/*virtual*/ void Ogre::HandleEvent(const SGD::Event* pEvent) /*override*/
{
	if (pEvent->GetEventID() == "THROW_ROCK")
	{
		SGD::Point playerPos = GameplayState::GetInstance()->GetPlayer()->GetPosition();

		SGD::Vector orientation = { 0.0f, -1.0f };
		SGD::Vector toPlayer = SGD::Point(playerPos.x, playerPos.y - 15) - GetWeaponOffset();
		float angleToPlayer = orientation.ComputeAngle(toPlayer);

		if (orientation.ComputeSteering(toPlayer) < 0.0f)
			angleToPlayer = -angleToPlayer;

		CreateBulletMessage * Msg = new CreateBulletMessage{ this, angleToPlayer, false };
		Msg->QueueMessage();
	}
	else
		MovingObject::HandleEvent(pEvent);
}

void Ogre::HandleCollision(GameObject* pOther)
{
	if (pOther->GetType() == MovingObject::OBJ_BULLET)
	{
		// don't shoot yourself
		if (((Projectile *)pOther)->GetOwner() == this) return;

		// call MovingObjects HandleCollision
		MovingObject::HandleCollision(pOther);
		// play hit sfx
		SGD::AudioManager::GetInstance()->PlayAudio(damageAudio);
	}

	if (pOther->GetType() == MovingObject::OBJ_PLAYER)
	{
		if (animInfo.GetCurrAnimation() == "ogrecharging")
		{
			chargeTargetSet = false;

			StartAnimation("ogresmash");
			chargingTimer = 0.0f;
		}

	}
	CharacterCollision(pOther);
}
